% -------------------------------------------------------------------------
% MAIN
% -------------------------------------------------------------------------

global EPOCHS;
global LAYERS;
global ETA;
global k_eta_adap;

format long;
constants;

%patterns = get_patterns();
load patterns;

training_patterns = patterns{1}(1:3,:);
S_training_patterns = normalize_outputs(patterns{1}(4,:));
testing_patterns = patterns{2}(1:3,:);
S_testing_patterns = normalize_outputs(patterns{2}(4,:));

weights = matrix_weights();
alpha = ALPHA;

k_eta_adap = 0;
for epoch = 1:EPOCHS
    shuffle_p = shuffle_patterns(training_patterns, S_training_patterns);
    training_patterns = shuffle_p(1:3,:);
    S_training_patterns = shuffle_p(4,:);
    
    for i = 1:length(training_patterns)
        ret = feed_forward(weights, training_patterns(:,i), S_training_patterns(i));
        deltas = ret{1};
        h = ret{2};
        delta_weights = back_propagation(weights, deltas, h, training_patterns(:,i));
        for j = 1:length(LAYERS)
            weights{j} = weights{j} + delta_weights{j};
            if i > 1
                weights{j} = weights{j} + alpha * previous_delta_weights{j};
            end
        end
        previous_delta_weights = delta_weights;
    end
    
    o = compute_outputs(weights, testing_patterns);
    m = compute_outputs(weights, training_patterns);
    cost = cost_function(S_testing_patterns, o);
    costM = cost_function(S_training_patterns, m);

    msg = sprintf('Cost G: %g | Cost M: %g | ETA: %g | Epoch: %d', cost, costM, ETA, epoch);
    disp(msg);
    
    if epoch > 1
        ETA = adaptative_eta(cost, previous_cost);
        e(epoch) = ETA;
        if cost > previous_cost && ALPHA > 0
            alpha = 0;
            weights = previous_weights_epoch;
        else
            alpha = ALPHA;
        end
    end
    previous_cost = cost;
    previous_weights_epoch = weights;
end

msg = sprintf('Epochs limit reached! Cost: %g', cost);
disp(msg);

o = denormalize_outputs(o);
S_testing_patterns = denormalize_outputs(S_testing_patterns);
for i = 1:length(testing_patterns)
    disp('Pattern: ');
    disp(testing_patterns(:,i)');
    disp('Output: ');
    disp(o(i));
    disp('Desired: ');
    disp(S_testing_patterns(i));
end
